# 列表list与元组tuple
# 列表和元组都是有序的、可以存储任意类型数据的集合
# 列表是动态的,长度可变,可以随意的增加、删减或改变元素。列表的存储空间略大于元组、性能略逊于元组
# 元组是静态的,长度大小固定,不可以对元素进行增加、删减或者改变操作。元组相对于列表更加轻量级、性能稍优
# 元组的存储空间固定,且不可以修改,因此相对来说,元组比列表更轻量级,性能速度要略优于列表。
# 如果存储的是静态数据,数据和数量不变,那么使用元组更合适
# 如果存储的是动态数据,经常会对数据进行修改,那么应该使用列表
# 在数据量确定、且不会修改的场景下,尽量用元组,这样程序性能更好
if __name__ == '__main__':
    l = [1, 2, 'hello', 'world']  # 列表中同时包含int和string类型的元素
    print(l)

    tup = ('Tom', 'Jerry', 1, 2)  # 元组中同时包含int和string类型的元素
    print(tup)

    # 列表是动态的，长度大小不固定，可以随意地增加、删减或者改变元素（mutable）
    l = [1, 2, 3, 4]
    l[3] = 40  # 通过l[3]访问列表的第4个元素
    l.append(5)  # 在列表末尾追加元素
    print(l)

    # 元组是静态的，长度大小固定，无法增加删减或者改变（immutable）
    tup = (1, 2, 3, 4)
    # tup[3] = 40  # 报错:不支持修改元组内的元素
    new_tup = tup + (5,)  # 如果想修改元组内的元素,只能新开辟一块内存,创建新的元组
    print(new_tup)

    # Python 中的列表和元组都支持负数索引，-1 表示最后一个元素，-2 表示倒数第二个元素，以此类推
    print('l[-1] = ', l[-1])
    print('tup[-2] = ', tup[-2])

    # 列表和元组都支持切片操作,l[start:end]表示取[start,end)范围内的切片
    print('l[1:3] = ', l[1:3])
    print('tup[1:3] = ', tup[1:3])

    # 列表和元组可以通过 list() 和 tuple() 函数相互转换：
    print('list((1,2,3)) = ', list((1, 2, 3)))
    print('tuple([1,2,3]) = ', tuple([1, 2, 3]))

    # 列表的内置函数
    l = [3, 2, 3, 7, 8, 1]
    print('l.count(3) = ', l.count(3))  # count:统计元素出现的次数
    print('l.index(7) = ', l.index(7))  # index:统计元素第一次出现的索引
    # print('l.index(9) = ', l.index(9))  # 如果元素不存在会报错
    l.sort()  # sort:将列表按照升序排序
    print('l = ', l)
    l.reverse()  # reverse:将列表反转
    print('l = ', l)

    # 元组的内置函数
    tup = [3, 2, 3, 7, 8, 1]
    print('tup.count(3) = ', tup.count(3))  # count:统计元素出现的次数
    print('tup.index(7) = ', tup.index(7))  # index:统计元素第一次出现的索引
    # print('tup.index(9) = ', tup.index(9))  # 如果元素不存在会报错
    print(list(sorted(tup)))  # 内置函数sorted,返回一个升序排序后的迭代器
    print(list(reversed(tup)))  # 内置函数reversed,返回一个反转后的迭代器

    # 列表和元组存储方式不同,就决定了二者所占用的内存空间大小不同
    l = [1, 2, 3]
    print('l size = ', l.__sizeof__())
    tup = (1, 2, 3)
    print('tup size = ', tup.__sizeof__())
